package com.shigu.passageway.processes;

import com.opentae.data.mall.beans.*;
import com.opentae.data.mall.examples.MoBankLinknoExample;
import com.opentae.data.mall.examples.MoPassagewayAccountExample;
import com.opentae.data.mall.examples.MoWxuserinfoExample;
import com.opentae.data.mall.interfaces.*;
import com.shigu.agent.exceptions.AgentException;
import com.shigu.agent.processes.AgentProcess;
import com.shigu.main4.common.util.MoneyUtil;
import com.shigu.main4.common.util.SecretUtil;
import com.shigu.passageway.Passageway;
import com.shigu.passageway.bo.RegistBO;
import com.shigu.passageway.exceptions.PassagewayException;
import com.shigu.passageway.exceptions.UnpayException;
import com.shigu.wx.web.WxTempleateBaseData;
import com.shigu.wx.web.services.WxTokenService;
import com.unpay.skb.requests.ModifyRateRequest;
import com.unpay.skb.requests.ModifyRegistRequest;
import com.unpay.skb.requests.RegistCertificatesRequest;
import com.unpay.skb.requests.ReplacePayRequest;
import com.unpay.skb.responses.ModifyRateResponse;
import com.unpay.skb.responses.ModifyRegistResponse;
import com.unpay.skb.responses.RegistCertificatesResponse;
import com.unpay.skb.responses.ReplacePayResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service("unpayPassageway")
public class UnpayPassageway implements Passageway {
    private static final Logger logger = LoggerFactory.getLogger(UnpayPassageway.class);

    private final Long passagewayId=2L;

    @Autowired
    MoPassagewayAccountMapper moPassagewayAccountMapper;

    @Autowired
    MoOrderMapper moOrderMapper;

    @Autowired
    MoCardMapper moCardMapper;

    @Autowired
    ManagerUserMapper managerUserMapper;

    @Autowired
    MoSettlementMapper moSettlementMapper;

    @Autowired
    AgentProcess agentProcess;

    @Autowired
    MoShareProfitMapper moShareProfitMapper;

    @Autowired
    MoWxuserinfoMapper moWxuserinfoMapper;

    @Autowired
    WxTokenService wxTokenService;

    @Autowired
    MoBankLinknoMapper moBankLinknoMapper;

    @Autowired
    MoPassagewayMapper moPassagewayMapper;

    private Double defaultRate;
    private Double systemRate;
    private Double cashMoney;

    @Value("${me.flag}")
    private String OEM_FLAG;

    @Value("${wx.template.payed}")
    private String PAYED_NOTIFY;

    @Value("${wx.notify.admin}")
    private String ADMIN_NOTIFY;

    @Value("${main_host}")
    private String MAIN_HOST;

    @Value("${main_host}")
    String HOST;

    @PostConstruct
    public void init(){
        MoPassageway passageway=moPassagewayMapper.selectByPrimaryKey(passagewayId);
        defaultRate=Double.valueOf(passageway.getSysMax());
        systemRate=Double.valueOf(passageway.getSysMin());
        cashMoney=Double.valueOf(passageway.getCashMoney());
    }

    @Override
    public String regist(RegistBO bo) throws PassagewayException {
        Double rate=bo.getRate()==null||bo.getRate()<systemRate?defaultRate:bo.getRate();
        RegistCertificatesRequest request=new RegistCertificatesRequest();
        SimpleDateFormat sdf=new SimpleDateFormat("yyMMddHHmmss");
        DecimalFormat df=new DecimalFormat("000");
        String subMchId=sdf.format(new Date())+df.format(bo.getUserId()%1000);
        request.setSubMchId(subMchId);
        request.setSubMerName(bo.getRealName());
        request.setSubMerAddr(bo.getBankLocation());
        request.setIdNo(bo.getIdCard());
        request.setPhoneNo(bo.getTelephone());
        request.setSettAcctName(bo.getRealName());
        request.setSettAcct(bo.getBankAccountNumber());
        request.setMerCommisionValue(MoneyUtil.formatMoney(rate*100));
//        request.setTxMerCommisionValue(defaultRate*100+"");
        request.setTxMerFee(cashMoney.toString());
        RegistCertificatesResponse response=request.exec();
        if (!response.isSuccess()) {
            throw new UnpayException(response.getMsg());
        }
        MoPassagewayAccount account=new MoPassagewayAccount();
        account.setTelephone(bo.getTelephone());
        account.setAreaCode(bo.getAreaCode());
        account.setAccountCode(subMchId);
        account.setRealName(bo.getRealName());
        account.setBankUser(bo.getRealName());
        account.setRate(rate.toString());
        account.setPassagewayId(passagewayId);
        account.setUserId(bo.getUserId());
        account.setBankLocation(bo.getBankLocation());
        account.setBankName(bo.getBankName());
        account.setBankNumber(bo.getBankAccountNumber());
        account.setBodyNumber(bo.getIdCard());
        account.setUsedStatus(false);
        account.setCashMoney(bo.getCashMoney()==null?MoneyUtil.formatMoney(cashMoney):bo.getCashMoney());
        account.setLastModifyTime(new Date());
        moPassagewayAccountMapper.insertSelective(account);
        return subMchId;
    }

    @Override
    public String updateInfo(RegistBO bo) throws PassagewayException {
        //查出老账户
        MoPassagewayAccount account=moPassagewayAccountMapper.selByUserId(bo.getUserId(),passagewayId);
        ModifyRegistRequest request=new ModifyRegistRequest();
        request.setSubMchId(account.getAccountCode());
        request.setIdNo(bo.getIdCard());
        request.setPhoneNo(bo.getTelephone());
        request.setSettAcctName(bo.getRealName());
        request.setSettAcct(bo.getBankAccountNumber());
        ModifyRegistResponse res=request.exec();
        if (res.isSuccess()) {
            MoPassagewayAccount yp=new MoPassagewayAccount();
            yp.setBankName(bo.getBankName());
            yp.setBankNumber(bo.getBankAccountNumber());
            yp.setBankLocation(bo.getBankLocation());
            yp.setAccountId(account.getAccountId());
            yp.setBankUser(bo.getRealName());
            yp.setRealName(bo.getRealName());
            yp.setTelephone(bo.getTelephone());
            yp.setLastModifyTime(new Date());
            yp.setCashMoney(bo.getCashMoney()==null?MoneyUtil.formatMoney(cashMoney):bo.getCashMoney());
            moPassagewayAccountMapper.updateByPrimaryKeySelective(yp);
        }
        return account.getAccountCode();
    }

    @Override
    public String toPay(Long userId, Long creditCardId, Double withdrawalMoney) throws PassagewayException {
        //查出本通道账户，查出信用卡
        MoPassagewayAccountExample accountExample=new MoPassagewayAccountExample();
        accountExample.createCriteria().andUserIdEqualTo(userId).andPassagewayIdEqualTo(passagewayId);
        List<MoPassagewayAccount> accounts=moPassagewayAccountMapper.selectByExample(accountExample);
        if (accounts.size()==0) {
            throw new UnpayException("请先激活通道");
        }
        MoPassagewayAccount account=accounts.get(0);
        MoCard card=moCardMapper.selectByPrimaryKey(creditCardId);
        if (card == null) {
            throw new UnpayException("无效信用卡");
        }
        MoOrder order=new MoOrder();
        order.setUserId(userId);
        order.setMcc("6301");
        order.setRate(account.getRate());
        order.setPassagewayId(passagewayId);
        order.setCreditIcon(card.getBankIcon());
        order.setCreditBank(card.getBankName());
        order.setMoney(MoneyUtil.formatMoney(withdrawalMoney));
        order.setMobileName(account.getTelephone());
        order.setCreditNo(card.getBankNo());
        order.setCashNo(account.getBankNumber());
        order.setSource("B");
        order.setCreateTime(new Date());
        moOrderMapper.insertSelective(order);
        return HOST+"bus/unpay.htm?id="+order.getOrderId().toString();
    }

    @Override
    public void payCallBack(Long orderId, Double amount, Double fee, String paystatus) throws PassagewayException {
        //重复推跳过
        MoOrder order=moOrderMapper.selectByPrimaryKey(orderId);
        if (order.getStatus().equals(3)) {
            return;
        }
        if (!paystatus.equals("SUCCESS")) {
            return;
        }
        MoOrder updateOrder=new MoOrder();
        updateOrder.setFee(MoneyUtil.formatMoney(fee));
        updateOrder.setStatus(3);
        updateOrder.setOrderId(orderId);
        moOrderMapper.updateByPrimaryKeySelective(updateOrder);

        order.setStatus(3);
        order.setFee(updateOrder.getFee());

        String settlementFee= MoneyUtil.formatMoney(amount-fee);
        //结算记录走一波
        MoSettlement settlement=new MoSettlement();
        settlement.setOrderId(orderId);
        settlement.setSettlementTime(new Date());
        settlement.setMoney(settlementFee);
        //得到开户行信息
        //查出付款主体账户
        MoPassagewayAccountExample accountExample=new MoPassagewayAccountExample();
        accountExample.createCriteria().andPassagewayIdEqualTo(passagewayId).andUserIdEqualTo(order.getUserId());
        List<MoPassagewayAccount> accounts=moPassagewayAccountMapper.selectByExample(accountExample);
        if (accounts.size()==0) {
            logger.error(orderId+" 中付账户体系不存在");
            return;
        }
        MoPassagewayAccount account=accounts.get(0);
        settlement.setBankName(account.getBankName());
        settlement.setBankNumber(account.getBankNumber());
        settlement.setStatus(1);
        SimpleDateFormat sdf=new SimpleDateFormat("yMMddHHmmss");
        DecimalFormat df=new DecimalFormat("000000");
        settlement.setSettlementCode(sdf.format(new Date())+df.format(order.getOrderId()));
        settlement.setCashMoney(account.getCashMoney());
        moSettlementMapper.insertSelective(settlement);
        //代付走一波

        ReplacePayRequest payRequest=new ReplacePayRequest();
        payRequest.setSubMchId(account.getAccountCode());
        payRequest.setSubMchName(account.getRealName());
        payRequest.setSettAcct(account.getBankNumber());
        payRequest.setSettAcctName(account.getRealName());
        payRequest.setIdNo(account.getBodyNumber());
        payRequest.setPhoneNo(account.getTelephone());
        Double amtSent=(amount-fee-Double.valueOf(account.getCashMoney()))*100;
        payRequest.setTotalAmt(String.valueOf(amtSent.longValue()));
        payRequest.setOrderId(order.getOrderCode());
        payRequest.setPaidOrderId(settlement.getSettlementCode());
        payRequest.setBatchNo("1");
        payRequest.setPaidType("0");
        payRequest.setTranType("0");
        payRequest.setMerCbName(account.getBankName());
        //取联行号
        payRequest.setMerCbCode(selLinkNo(account.getBankNumber()));
        ReplacePayResponse payResponse=payRequest.exec();
        if (payResponse.isSuccess()) {
            toMakeProfit(settlement.getSettlementId(),order);
        }
    }

    /**
     * 取联行号
     * @return
     */
    private String selLinkNo(String bankCard){
        //查一下，这个卡已经有了，就拿已有的
        MoBankLinknoExample example=new MoBankLinknoExample();
        example.createCriteria().andBankCardEqualTo(bankCard);
        List<MoBankLinkno> linknos=moBankLinknoMapper.selectByExample(example);
        if (linknos.size()>0) {
            return linknos.get(0).getLinkno();
        }
        //调用接口去取联行号
        return "";
    }

    /**
     * 给代理分润
     * @param settlementId
     * @throws UnpayException
     */
    public void toMakeProfit(Long settlementId,MoOrder order) throws UnpayException {

        //代理费率
        SettleRate settAgentRate=managerUserMapper.selAgentRateBySettleId(settlementId,passagewayId);
        if (settAgentRate == null) {
            throw new UnpayException(order.getOrderId()+"_取代理分润信息失败");
        }
        Double agentRate=settAgentRate.getRate();
        if (agentRate == null||agentRate<systemRate) {
            agentRate=systemRate;
        }
        //实际手续费-代理的成本手续费=代理的利润
        Double profitMoney=Double.valueOf(order.getFee())-Double.valueOf(settAgentRate.getTradeMoney())*agentRate;
        if (profitMoney>0) {//如果等于0就没什么好分的啦
            //加余额
            try {
                agentProcess.increaseProfile(settAgentRate.getUserId(),profitMoney);
            } catch (AgentException e) {
                throw new UnpayException(e.getMessage());
            }
        }else{
            profitMoney=0d;
        }
        MoShareProfit profit=new MoShareProfit();
        profit.setAgentId(settAgentRate.getUserId());
        profit.setBusinessId(order.getUserId());
        profit.setCreateTime(new Date());
        profit.setOrderId(settAgentRate.getOrderId());
        profit.setTradeMoney(settAgentRate.getTradeMoney());
        profit.setProfitMoney(profitMoney.toString());
        profit.setCostRate(order.getRate());
        DecimalFormat df=new DecimalFormat("0.0000");
        profit.setAgentRate(df.format(agentRate));
        moShareProfitMapper.insertSelective(profit);

        if (profitMoney<=0) {
            return;
        }

        ManagerUser user=managerUserMapper.selectByPrimaryKey(order.getUserId());

        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        //发送分润提醒，先查出代理openid如果 没有则不发
        MoWxuserinfoExample wxExample=new MoWxuserinfoExample();
        wxExample.createCriteria().andUserIdEqualTo(settAgentRate.getUserId());
        wxExample.setStartIndex(0);
        wxExample.setEndIndex(1);
        List<MoWxuserinfo> wxinfos=moWxuserinfoMapper.selectByConditionList(wxExample);
        Map<String,WxTempleateBaseData> wxTempleateDataMap=new HashMap<>();
        wxTempleateDataMap.put("first",new WxTempleateBaseData("恭喜你，获得一笔分润佣金！"));
        wxTempleateDataMap.put("keyword1",new WxTempleateBaseData(MoneyUtil.formatMoney(profitMoney)));
        wxTempleateDataMap.put("keyword2",new WxTempleateBaseData(sdf.format(new Date())));
        wxTempleateDataMap.put("remark",new WxTempleateBaseData(SecretUtil.secretName(user.getRealName()) +
                "消费了"+MoneyUtil.formatMoney(order.getMoney())+"元"));
        String targetopenid="";
        if (wxinfos.size()>0) {
            MoWxuserinfo wxuser=wxinfos.get(0);
            try {
                String token=wxTokenService.getSystemToken().getAccess_token();
                wxTokenService.sendTemplateMsg(PAYED_NOTIFY,wxuser.getOpenId(),wxTempleateDataMap,MAIN_HOST+"wappage/agpage/tradeDetail",token);
                targetopenid=wxuser.getOpenId();
            } catch (Exception e) {
                logger.error("获取token失败",e);
            }
        }
        //发给老赵一份
        if (!ADMIN_NOTIFY.equals(targetopenid)) {
            wxTempleateDataMap.put("first",new WxTempleateBaseData("恭喜["+settAgentRate.getUserId()+"]，获得一笔分润佣金！","#9E272A"));
            try {
                String token=wxTokenService.getSystemToken().getAccess_token();
                wxTokenService.sendTemplateMsg(PAYED_NOTIFY,ADMIN_NOTIFY,wxTempleateDataMap,MAIN_HOST+"wappage/agpage/tradeDetail",token);
            } catch (Exception e) {
                logger.error("发消息失败",e);
            }
        }
    }

    @Override
    public void setFee(Long agentId, Long businessId, Double rate,Double settleMoney) throws PassagewayException {
        rate=rate/100;
        MoPassagewayAccountExample accountExample=new MoPassagewayAccountExample();
        accountExample.createCriteria().andUserIdEqualTo(agentId).andPassagewayIdEqualTo(2L);
        accountExample.setStartIndex(0);
        accountExample.setEndIndex(1);
        List<MoPassagewayAccount> ageentunpays=moPassagewayAccountMapper.selectByConditionList(accountExample);
        Double limitRate=systemRate;
        if (ageentunpays.size()>0) {
            limitRate=Double.valueOf(ageentunpays.get(0).getRate());
        }
        superSetFee(businessId,rate,limitRate,settleMoney);
    }

    @Override
    public void superSetFee(Long userId, Double rate, Double limitRate,Double settleMoney) throws PassagewayException {
        if(rate<limitRate){
            new UnpayException("商户费率不能小于代理费率").throwMe();
        }
        MoPassagewayAccountExample accountExample=new MoPassagewayAccountExample();
        accountExample.createCriteria().andUserIdEqualTo(userId).andPassagewayIdEqualTo(2L);
        accountExample.setStartIndex(0);
        accountExample.setEndIndex(1);
        MoPassagewayAccount unpay=moPassagewayAccountMapper.selectByConditionList(accountExample).get(0);

        ModifyRateRequest mrr=new ModifyRateRequest();
        mrr.setSubMchId(unpay.getAccountCode());
        String rateStr=MoneyUtil.dealRate(rate.toString()).replace("%","");
        mrr.setMerCommisionValue(rateStr);
        mrr.setTxMerCommisionValue(rateStr);
        ModifyRateResponse res=mrr.exec();
        if (res.isSuccess()) {
            MoPassagewayAccount updateAccount=new MoPassagewayAccount();
            updateAccount.setRate(rate.toString());
            if (settleMoney != null) {
                updateAccount.setCashMoney(MoneyUtil.formatMoney(settleMoney));
            }
            moPassagewayAccountMapper.updateByExampleSelective(updateAccount,accountExample);
        }
    }

    @Override
    public Double getSystemRate() {
        return null;
    }


}
